﻿using System.Collections.Generic;
using System.Linq;
using BingleMaps.Extensions;
using GalaSoft.MvvmLight;
using Microsoft.Phone.Controls.Maps.Platform;
using Serialization;

namespace BingleMaps.Models
{
	public class UserPinEx : ViewModelBase
	{
		#region statics
		public enum IconKey { General, Bicycle, Vehicle, Drink, Fuel, Property, Restaurant, Shop, Hospital }
		[DoNotSerialize]
		private static readonly Dictionary<IconKey, string> _availableIcons = new Dictionary<IconKey, string>
		{
			{ IconKey.General, "M50,0C22.43,0,0,22.43,0,50c0,27.569,22.43,50,50,50s50-22.431,50-50C100,22.43,77.57,0,50,0z M54.032,91.737V78.226h-8.064  v13.512C26.057,89.829,10.171,73.943,8.263,54.032h13.512v-8.064H8.263c1.909-19.911,17.794-35.796,37.705-37.705v13.511h8.064  V8.263c19.911,1.908,35.797,17.793,37.705,37.705H78.226v8.064h13.512C89.829,73.943,73.943,89.829,54.032,91.737z" },
			{ IconKey.Bicycle, "M 82.369,23.536 C 80.128,23.536 77.846,23.984 75.753,24.806 75.721,24.843 75.721,24.843 75.721,24.843 73.701,21.072 71.685,17.297 69.668,13.526 70.228,12.142 70.789,10.796 71.312,9.451 73.892,9.451 75.985,7.323 75.985,4.746 75.985,4.708 75.985,4.708 75.985,4.708 70.492,4.708 65,4.708 59.509,4.708 58.906,4.708 58.352,5.27 58.352,5.907 58.352,6.428 58.684,6.877 59.208,7.027 61.635,7.661 64.068,8.297 66.492,8.891 65.818,10.459 65.182,11.993 64.553,13.526 53.831,13.526 43.107,13.526 32.421,13.526 32.421,13.526 33.021,11.546 33.132,11.131 33.318,10.422 33.431,10.162 33.431,9.413 33.431,7.734 32.387,6.688 30.931,5.866 30.893,5.83 30.855,5.791 30.855,5.791 30.701,5.683 30.591,5.489 30.591,5.306 30.591,5.007 30.893,4.707 31.191,4.707 31.601,4.707 31.978,4.707 32.347,4.707 34.331,4.707 36.308,4.707 38.251,4.707 38.251,3.141 38.251,1.571 38.251,4.76837e-007 36.082,4.76837e-007 33.916,4.76837e-007 31.79,4.76837e-007 31.191,4.76837e-007 30.591,4.76837e-007 29.994,4.76837e-007 27.419,0.0400005 25.326,2.169 25.326,4.745 25.326,6.651 26.484,8.367 28.242,9.115 28.277,9.115 28.314,9.115 28.314,9.115 28.537,9.228 28.651,9.413 28.651,9.677 28.651,9.712 28.651,9.75 28.651,9.788 28.651,9.825 28.651,9.825 28.651,9.825 27.156,14.831 25.665,19.836 24.167,24.804 24.132,24.767 24.095,24.732 24.057,24.732 21.481,23.72 20.435,23.535 17.667,23.535 7.917,23.536 0,31.454 0,41.206 0,50.92 7.917,58.84 17.665,58.84 27.38,58.84 35.302,50.92 35.302,41.206 35.302,35.641 32.836,30.632 28.463,27.233 28.426,27.158 28.389,27.121 28.389,27.083 28.611,26.451 28.8,25.815 28.988,25.216 35.71,29.848 42.433,34.445 49.119,39.04 49.119,39.075 49.119,39.114 49.119,39.114 48.931,39.82 48.823,40.493 48.823,41.206 48.823,45.09 51.996,48.268 55.883,48.268 56.963,48.268 57.188,48.192 58.199,47.855 58.683,48.787 59.165,49.722 59.658,50.617 58.874,50.617 58.118,50.617 57.379,50.617 57.379,51.403 57.379,52.188 57.379,52.973 58.199,52.973 59.015,52.973 59.838,52.973 60.213,53.346 60.665,53.533 61.185,53.533 61.671,53.533 62.155,53.309 62.494,52.937 63.168,52.937 63.805,52.937 64.441,52.937 64.441,52.146 64.441,51.362 64.441,50.617 63.462,50.617 62.531,50.617 61.595,50.617 60.997,49.423 60.401,48.229 59.838,47.031 61.301,46.065 62.267,44.68 62.721,42.96 62.759,42.96 62.759,42.96 62.759,42.96 63.463,42.96 64.135,42.96 64.808,42.96 65.705,51.999 73.287,58.84 82.367,58.84 92.076,58.84 99.998,50.92 99.998,41.206 100,31.454 92.078,23.536 82.369,23.536 Z M 29.977,41.206 C 29.977,48.004 24.45,53.533 17.649,53.533 10.817,53.533 5.285,48.004 5.285,41.206 5.285,34.367 10.817,28.837 17.649,28.837 19.404,28.837 21.088,29.212 22.621,29.886 22.655,29.925 22.696,29.925 22.696,29.925 22.209,31.491 21.724,33.065 21.238,34.632 20.565,36.649 18.885,38.182 16.867,39.565 16.754,39.638 16.683,39.711 16.607,39.748 16.16,40.085 15.857,40.608 15.857,41.207 15.857,42.141 16.683,42.961 17.649,42.961 17.728,42.961 17.909,42.961 17.987,42.93 21.351,41.991 24.747,39.224 25.792,35.936 26.131,34.896 26.43,33.849 26.73,32.839 26.764,32.875 26.764,32.875 26.764,32.875 28.784,35.077 29.977,37.994 29.977,41.206 Z M 74.506,31.646 C 74.545,31.607 74.545,31.568 74.545,31.568 75.968,34.221 77.344,36.834 78.728,39.447 75.852,39.447 72.978,39.447 70.136,39.447 70.136,39.414 70.136,39.373 70.136,39.373 70.583,36.236 72.045,33.661 74.506,31.646 Z M 30.204,21.036 C 30.539,19.914 30.876,18.791 31.174,17.671 41.78,17.671 52.357,17.671 62.924,17.671 60.689,23.163 58.446,28.653 56.242,34.144 56.2,34.144 56.163,34.144 56.163,34.144 56.053,34.144 55.942,34.144 55.867,34.144 55.154,34.144 54.369,34.258 53.697,34.486 53.623,34.52 53.587,34.52 53.546,34.52 53.066,33.586 52.617,32.685 52.167,31.791 52.914,31.791 53.664,31.791 54.37,31.791 54.37,31.008 54.37,30.224 54.37,29.435 53.546,29.435 52.731,29.435 51.905,29.435 51.873,29.398 51.873,29.398 51.873,29.398 51.531,29.031 51.046,28.837 50.564,28.837 50.073,28.837 49.629,29.03 49.291,29.398 49.256,29.435 49.256,29.435 49.256,29.435 48.583,29.435 47.944,29.435 47.313,29.435 47.313,30.224 47.313,31.008 47.313,31.791 48.284,31.791 49.256,31.791 50.191,31.791 50.787,32.988 51.384,34.184 51.948,35.34 51.759,35.451 51.611,35.561 51.458,35.672 44.364,30.78 37.264,25.889 30.204,21.036 Z M 55.868,45.916 C 53.287,45.916 51.16,43.779 51.16,41.206 51.16,38.591 53.286,36.498 55.868,36.498 58.447,36.498 60.57,38.591 60.57,41.206 60.57,43.779 58.447,45.916 55.868,45.916 Z M 64.793,39.373 C 64.793,39.373 64.793,39.373 64.793,39.414 64.12,39.414 63.41,39.414 62.706,39.414 62.332,38.026 61.695,36.98 60.649,35.973 60.649,35.973 60.61,35.935 60.569,35.904 62.888,30.113 65.239,24.285 67.595,18.457 69.052,21.256 70.546,24.058 72.045,26.862 72.045,26.862 72.002,26.862 71.962,26.898 67.822,29.925 65.32,34.294 64.793,39.373 Z M 82.352,53.533 C 76.228,53.533 71.033,49.088 70.136,43.036 70.136,42.998 70.136,42.96 70.136,42.96 74.207,42.96 78.282,42.96 82.352,42.96 83.289,42.96 84.108,42.14 84.108,41.206 84.108,40.943 84.068,40.684 83.997,40.46 82.052,36.799 80.11,33.175 78.203,29.55 79.476,29.102 80.968,28.837 82.352,28.837 89.15,28.837 94.715,34.367 94.715,41.206 94.715,48.004 89.15,53.533 82.352,53.533 Z" },
			{ IconKey.Vehicle, "M90.925,28.696L82.728,7.529C81.195,3.477,77.845,0.029,71.505,0h-11.56H40.188H28.427  c-6.311,0.029-9.661,3.477-11.222,7.529L9.006,28.696C5.751,29.116-0.01,32.941,0,40.187v26.951h7.999v8.603  c-0.02,10.606,14.989,10.48,14.985,0v-8.603H50h26.948v8.603c0.033,10.48,15.042,10.606,15.052,0v-8.603h8V40.187  C99.975,32.941,94.21,29.116,90.925,28.696z M15.727,50.874c-3.834,0.011-6.938-3.187-6.922-7.12  c-0.016-3.96,3.088-7.161,6.922-7.128c3.822-0.033,6.926,3.168,6.921,7.128C22.653,47.687,19.548,50.884,15.727,50.874z M50,28.497  h-0.067H17.541l6.182-16.668c0.746-2.366,1.904-4.059,4.639-4.1h21.571H50H71.64c2.693,0.041,3.854,1.733,4.636,4.1l6.183,16.668H50  z M84.274,50.874c-3.861,0.011-6.967-3.187-6.988-7.12c0.021-3.96,3.127-7.161,6.988-7.128c3.795-0.033,6.898,3.168,6.922,7.128  C91.172,47.687,88.069,50.884,84.274,50.874z" },
			{ IconKey.Drink, "M80.449,87.847H56.407v-34.28L99.801,0H0l44.187,53.302v34.545H20.606c-8.151,0.019-8.151,12.153,0,12.153h59.843  C88.55,100,88.483,87.865,80.449,87.847z M50.132,30.055c-0.008-4.261,3.458-7.728,7.73-7.73c4.276,0.002,7.744,3.469,7.725,7.73  c0.02,4.292-3.448,7.756-7.725,7.728C53.589,37.811,50.124,34.348,50.132,30.055z" },
			{ IconKey.Fuel, "M35.705,29.44c0,1.316-1.041,2.34-2.365,2.34H8.587c-1.334,0-2.366-1.024-2.366-2.34V8.568c0-1.316,1.032-2.34,2.366-2.34  H33.34c1.324,0,2.365,1.024,2.365,2.34V29.44z M64.562,32.107c-3.132-0.688-4.268-2.297-4.268-3.778v-5.394  c0,0,2.082,0.465,2.581,0.594c1.015,0.267,1.66,1.824,1.687,3.184C64.596,28.073,64.562,32.107,64.562,32.107z M70.868,64.879  c0-0.052-0.868-6.625-0.868-6.625V27.9c0-3.252-1.067-5.894-3.27-8.113L52.671,5.798c-0.972,0-3.656,2.676-3.656,2.676  c0,0.972,6.978,7.898,6.978,7.898L55.786,28.15c0,4.182,3.398,7.571,7.598,7.571l1.884,0.026l-0.671,22.507l0.938,7.718  l4.225,22.774c0.156,3.699-3.227,5.901-5.894,5.901c-2.469,0-5.334-2.039-5.334-4.672l0.052-39.911c0-4.853-3.94-8.793-8.793-8.793  c0,0-8.44,0-8.483,0c0.594-0.033,0.619-26.137,0.619-31.678c0-0.655,0-1.025,0-1.025C41.925,3.845,38.071,0,33.339,0H8.587  C3.854,0,0,3.845,0,8.568V100h41.939l0.029-53.12h7.916c1.815,0,3.295,1.481,3.295,3.295v39.8c0,5.344,4.99,10.024,10.686,10.024  c5.377,0,11.399-4.276,11.399-10.024C75.17,88.65,70.868,64.879,70.868,64.879z" },
			{ IconKey.Property, "M99.585,49.144c-6.011-6.031-12.021-12.061-18.032-18.092c-0.306-0.307-0.52-0.484-0.665-0.578  c0.021-0.076,0.035-0.181,0.035-0.335c0-2.175,0-4.351,0-6.526c0-4.371,0-8.741,0-13.112c0-0.794-0.663-1.457-1.457-1.457  c-3.158,0-6.315,0-9.474,0c-0.794,0-1.457,0.663-1.457,1.457c0,2.497,0,4.993,0,7.49C62.7,12.136,56.865,6.281,51.03,0.426  c-0.304-0.304-0.645-0.424-0.975-0.424C50.037,0,50.019,0.001,50,0c-0.019,0.001-0.037,0-0.056,0.002  c-0.33,0-0.671,0.12-0.975,0.424C32.785,16.665,16.6,32.904,0.415,49.144c-0.897,0.899-0.243,2.486,1.03,2.486  c3.322,0,6.646,0,9.969,0c0,10.251,0,20.502,0,30.753c0,0.794,0.663,1.457,1.457,1.457c10.353,0,19.735,0,30.089,0  c0.793,0,1.456-0.663,1.456-1.457c0-7.171,0-14.342,0-21.514c3.075,0,8.093,0,11.168,0c0,7.172,0,14.343,0,21.514  c0,0.794,0.663,1.457,1.456,1.457c10.354,0,19.736,0,30.09,0c0.793,0,1.456-0.663,1.456-1.457c0-10.251,0-20.502,0-30.753  c3.323,0,6.646,0,9.969,0C99.827,51.63,100.482,50.043,99.585,49.144z" },
			{ IconKey.Restaurant, "M44.53051,0.040125515 C48.599262,0.040125161 52.667011,3.0283751 52.660011,9.0048752 L52.660011,94.146881 C52.674011,101.75288 42.048012,101.63988 42.03801,94.146881 L42.03801,60.343876 L36.395012,60.343876 L36.395012,9.0048752 C36.39201,3.0283751 40.461761,0.040125161 44.53051,0.040125515 z M1.8940114,1.8626451E-08 C2.8447618,0.00012503564 3.7995119,0.68087506 3.8120124,2.0928752 L3.8120124,24.405874 L6.9650126,24.405874 L6.9650126,1.8878757 C6.9650121,-0.51912498 10.617012,-0.67512488 10.626013,1.9908746 L10.626013,24.405874 L13.877012,24.405874 L13.877012,1.9388745 C13.901012,-0.60012496 17.450012,-0.70112491 17.435011,2.040875 L17.435011,24.405874 L20.690012,24.405874 L20.690012,1.9388745 C20.678011,-0.57412493 24.385012,-0.67612493 24.401011,2.040875 L24.401011,32.641876 L24.400011,32.641876 C24.382011,35.874874 21.423012,39.352875 17.588011,39.352875 L17.588011,94.146881 C17.587011,101.94988 6.9810119,101.94988 6.9650126,94.146881 L6.9650126,39.352875 C3.243012,39.352875 -0.0069880141,36.472874 1.1284588E-05,32.184875 L1.1284588E-05,1.9908746 C-0.003488014,0.68037498 0.94326198,-0.00012496114 1.8940114,1.8626451E-08 z" },
			{ IconKey.Shop, "M89.646004,71.858002 C95.364403,71.858002 100,76.493599 100,82.211998 C100,87.930397 95.364403,92.566002 89.646004,92.566002 C83.927696,92.566002 79.292,87.930397 79.292,82.211998 C79.292,76.493599 83.927696,71.858002 89.646004,71.858002 z M38.141998,71.858002 C43.860401,71.858002 48.495998,76.493599 48.495998,82.211998 C48.495998,87.930397 43.860401,92.566002 38.141998,92.566002 C32.423599,92.566002 27.788,87.930397 27.788,82.211998 C27.788,76.493599 32.423599,71.858002 38.141998,71.858002 z M0,0 L17.167999,0 L20.177,8.4960003 L100,6.1939998 L100,37.344002 L29.197001,51.974998 L29.202999,51.992001 C27.931999,52.490002 27.028,53.724998 27.028,55.169998 C27.028,57.053001 28.559999,58.584 30.441999,58.584 L100,58.584 L100,69.204002 L30.443001,69.204002 C22.705,69.204002 16.409,62.909 16.409,55.171001 C16.409,50.901001 18.333,47.078999 21.351999,44.504002 L8.4960003,6.1509995 L3.5400004,6.1509995 z" },
			{ IconKey.Hospital, "M63.237,56.404999 L63.237,100 L85.292,100 L85.292,0 L63.237,0 L63.237,34.831001 L22.058001,34.831001 L22.058001,0 L0,0 L0,100 L22.058001,100 L22.058001,56.404999 z" }
		};
		[DoNotSerialize]
		public static Dictionary<IconKey, string> AvailableIcons { get { return _availableIcons; } }
		[DoNotSerialize]
		public static KeyValuePair<IconKey, string> DefaultIcon = _availableIcons.First();

		public enum ColorKey { Blue, Magnenta, Purple, Teal, Lime, Brown, Pink, Orange, Red, Green }
		[DoNotSerialize]
		private static readonly Dictionary<ColorKey, string> _availableColors = new Dictionary<ColorKey, string>
		{
			{ColorKey.Blue,"#1BA1E2"},
			{ColorKey.Magnenta,"#FF0097"},
			{ColorKey.Purple,"#A200FF"},
			{ColorKey.Teal,"#00ABA9"},
			{ColorKey.Lime,"#8CBF26"},
			{ColorKey.Brown,"#A05000"},
			{ColorKey.Pink,"#E671B8"},
			{ColorKey.Orange,"#F09609"},
			{ColorKey.Red,"#E51400"},
			{ColorKey.Green,"#339933"}
		};
		[DoNotSerialize]
		public static Dictionary<ColorKey, string> AvailableColors { get { return _availableColors; } }
		[DoNotSerialize]
		public static readonly KeyValuePair<ColorKey, string> DefaultColor = AvailableColors.First();
		#endregion

		#region Sync Related
		public enum ChangeAction { Add, Delete, Update, None }
		public ChangeAction Change { get; set; }
		public long TimeStamp { get; set; }

		public bool LocationEquals(UserPinEx userPin)
		{
			return userPin != null
				&& userPin.Location != null
				&& Location != null
				&& Location.Latitude == userPin.Location.Latitude
				&& Location.Longitude == userPin.Location.Longitude;
		}
		#endregion

		[DoNotSerialize]
		private const string IsCheckedPropertyName = "IsChecked";
		[DoNotSerialize]
		private bool _isChecked;
		[DoNotSerialize]
		public bool IsChecked
		{
			get { return _isChecked; }
			set
			{
				if (value == _isChecked) return;
				_isChecked = value;
				RaisePropertyChanged(IsCheckedPropertyName);
			}
		}

		private const string LocationPropertyName = "Location";
		private Location _location;
		public Location Location
		{
			get { return _location; }
			set
			{
				if (value == _location) return;
				_location = value;
				RaisePropertyChanged(LocationPropertyName);
			}
		}

		private const string IsTemporaryPropertyName = "IsTemporary";
		private bool _isTemporary;
		public bool IsTemporary
		{
			get { return _isTemporary; }
			set
			{
				if (value == _isTemporary) return;
				_isTemporary = value;
				RaisePropertyChanged(IsTemporaryPropertyName);
			}
		}

		[DoNotSerialize]
		public IEnumerable<char> ShortCoordinates { get { return Location.ToLatLngString(); } }

		private const string NotePropertyName = "Note";
		private string _note;
		public string Note
		{
			get { return _note; }
			set
			{
				if (value == _note) return;
				_note = value;
				RaisePropertyChanged(NotePropertyName);
			}
		}

		private const string ImagePropertyName = "Image";
		private string _image;
		public string Image
		{
			get { return _image; }
			set
			{
				if (value == _image) return;
				_image = value;
				RaisePropertyChanged(ImagePropertyName);
			}
		}

		private const string ColorPropertyName = "Color";
		private ColorKey _color = DefaultColor.Key;
		public ColorKey Color
		{
			get { return _color; }
			set
			{
				if (value == _color) return;
				_color = value;
				RaisePropertyChanged(ColorPropertyName);
			}
		}

		[DoNotSerialize]
		private const string IsHeldPropertyName = "IsHeld";
		[DoNotSerialize]
		private bool _isHeld;
		[DoNotSerialize]
		public bool IsHeld
		{
			get { return _isHeld; }
			set
			{
				if (value == _isHeld) return;
				_isHeld = value;
				RaisePropertyChanged(IsHeldPropertyName);
			}
		}

		private const string IsExpandedPropertyName = "IsExpanded";
		private bool _isExpanded;
		public bool IsExpanded
		{
			get { return _isExpanded; }
			set
			{
				if (value == _isExpanded) return;
				_isExpanded = value;
				RaisePropertyChanged(IsExpandedPropertyName);
			}
		}

		private const string TitlePropertyName = "Title";
		private string _title = "my pin";
		public string Title
		{
			get { return _title; }
			set
			{
				if (value == _title) return;
				_title = value;
				RaisePropertyChanged(TitlePropertyName);
			}
		}

		private const string AddressPropertyName = "Address";
		private string _address;
		public string Address
		{
			get { return _address; }
			set
			{
				if (value == _address) return;
				_address = value;
				RaisePropertyChanged(AddressPropertyName);
				Display = value ?? Location.ToLatLngString();
			}
		}

		[DoNotSerialize]
		private const string DisplayPropertyName = "Display";
		[DoNotSerialize]
		private string _display;
		[DoNotSerialize]
		public string Display
		{
			get { return _display; }
			set
			{
				if (value == _display) return;
				_display = value;
				RaisePropertyChanged(DisplayPropertyName);
			}
		}

		private const string IconPropertyName = "Icon";
		private IconKey _icon = DefaultIcon.Key;
		public IconKey Icon
		{
			get { return _icon; }
			set
			{
				if (value == _icon) return;
				_icon = value;
				RaisePropertyChanged(IconPropertyName);
			}
		}
	}
}
